<?php
/**
 * TCP通讯连接池
 */
declare(strict_types=1);

namespace Libraries\Connections;

use Swoole\ConnectionPool;
use Libraries\Connections\Drivers\TcpSocket;
use Libraries\Config;

class TcpConn
{
    private static $arrPool = [];

    /**
     * 从连接池中取出一个
     * @param string $strName
     * @return TcpSocket|null
     */
    public static function get(string $strName = ''): ?TcpSocket
    {
        strlen($strName) || $strName = 'default';
        $objPool = self::init($strName, true);
        return $objPool ? $objPool->get() : null;
    }

    /**
     * 归还一个连接
     * @param TcpSocket|null $objSocket
     * @param string $strName
     * @return void
     */
    public static function put(?TcpSocket $objSocket, string $strName = ''): void
    {
        strlen($strName) || $strName = 'default';
        $objPool = self::init($strName);
        $objPool && $objPool->put($objSocket);
    }

    /**
     * 关闭连接池
     * @param string $strName
     * @return void
     */
    public static function close(string $strName = ''): void
    {
        if (strlen($strName)) {
            $objPool = self::init($strName);
            $objPool && $objPool->close();
            unset(self::$arrPool[$strName]);
        } else {
            foreach (self::$arrPool as $strName => $objPool) {
                $objPool && $objPool->close();
                unset(self::$arrPool[$strName]);
            }
        }
    }

    /**
     * 取连接池
     * @param string $strName
     * @param bool $blnSetNx
     * @return ConnectionPool|null
     */
    private static function init(string $strName, bool $blnSetNx = false): ?ConnectionPool
    {
        if (isset(self::$arrPool[$strName])) {
            return self::$arrPool[$strName];
        }
        if (!$blnSetNx) {
            return null;
        }
        $intSize = 0;
        $arrConfig = Config::get('tcp_server_' . $strName);
        $arrConfig || $arrConfig = Config::get('tcp_server');
        if ($arrConfig) {
            $intSize = intval($arrConfig['pool_size'] ?? 5);
            unset($arrConfig['pool_size']);
        }
        if ($intSize > 0) {
            self::$arrPool[$strName] = new ConnectionPool(function () use ($arrConfig) {
                $arrConfig = array_values($arrConfig);
                return new TcpSocket(...$arrConfig);
            }, $intSize);
            return self::$arrPool[$strName];
        }
        return null;
    }
}
